#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <cstdio>
#include <string>
#include <strings.h>
#include <unistd.h>
#include <pthread.h>

void Usage(char *proc)
{
  std::cout << "\n\tUsage: " << proc << " serverip serverport" << std::endl;
}

struct ThreadData
{
  int sockfd;
  struct sockaddr_in server;
  std::string severip;
};

void *recvfrom(void *args)
{
  struct ThreadData *td = static_cast<struct ThreadData *>(args);
  char buffer[1024];
  while (true)
  {
    struct sockaddr_in temp;
    socklen_t len = sizeof(temp);
    // 接收服务器返回的消息
    ssize_t rcv = recvfrom(td->sockfd, buffer, 1023, 0, (struct sockaddr *)&temp, &len);
    if (rcv > 0)
    {
      buffer[rcv] = 0;
      std::cerr << buffer << std::endl;
    }
  }
}

void *sendfrom(void *args)
{
  struct ThreadData *td = static_cast<struct ThreadData *>(args);
  std::string message;
  socklen_t len = sizeof(td->server);

  std::string welcome = td->severip;
  welcome += "coming......, welcom to here, please send a photo of you";
  sendto(td->sockfd, welcome.c_str(), welcome.size(), 0, (struct sockaddr *)&td->server, len);
  while (true)
  {
    std::cout << "Please Enter@ ";
    getline(std::cin, message);

    sendto(td->sockfd, message.c_str(), message.size(), 0, (struct sockaddr *)&td->server, len);
  }
}

int main(int argc, char *argv[])
{
  if (argc != 3)
  {
    Usage(argv[0]);
    exit(0);
  }

  std::string serverip = argv[1];
  uint16_t serverport = std::stoi(argv[2]);
  // 创建一个套接字
  int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
  if (sockfd < 0)
  {
    std::cout << "sockfd create failed" << std::endl;
    return 1;
  }

  struct sockaddr_in server;
  bzero(&server, sizeof(server));
  server.sin_family = AF_INET;
  server.sin_addr.s_addr = inet_addr(serverip.c_str());
  server.sin_port = htons(serverport);
  socklen_t len = sizeof(server);

  struct ThreadData td;
  td.sockfd = sockfd;
  td.server = server;

  pthread_t recv, send;
  // 发送消息到服务器
  pthread_create(&send, nullptr, sendfrom, &td);
  // 接收服务器的消息
  pthread_create(&recv, nullptr, recvfrom, &td);

  pthread_join(recv, nullptr);
  pthread_join(send, nullptr);

  close(sockfd);

  return 0;
}